package com.walala.logic.threads;

import javafx.concurrent.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.*;

/**
 * @author KayLi
 */
public class BlockThreadPool implements IThreadPool {

    private Logger logger = LoggerFactory.getLogger(BlockThreadPool.class);

    /**
     * Q的大小
     */
    private int limit;

    private BlockingQueue<Runnable> Queue;

    private volatile boolean isRunning = true;

    private ThreadPoolExecutor threadPool;

    private int corePoolSize;

    private Thread monitorThreads;

    private String threadPoolName;


    public BlockThreadPool(final int corePoolSize, final int queueSize, String threadPoolName){
        Queue = new LinkedBlockingDeque<Runnable>(queueSize);
        ThreadFactory factory = new ThreadFactory() {
            private int count;
            @Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setName(threadPoolName+"_"+count);
                t.setDaemon(false);
                count++;
                return t;
            }
        };

        threadPool = new ThreadPoolExecutor(corePoolSize, corePoolSize, 0L, TimeUnit.MICROSECONDS, Queue, factory);
        if(Queue!=null){
            this.limit = Queue.remainingCapacity();
        }
        this.corePoolSize = corePoolSize;
        this.threadPoolName = threadPoolName;
    }

    @Override
    public int addTask(Runnable task) {
        try {
            threadPool.submit(task);
        } catch (Exception e) {
            if(task == null) {
                return -2;
            }
            try {
                threadPool.getQueue().put(task);
            } catch (InterruptedException e1) {
                logger.error("",e1);
                return -3;
            }
        }
        return Queue.remainingCapacity();
    }

    @Override
    public void shutDown() {

        //关闭线程池中的线程
        threadPool.shutdown();
        //关闭开关
        this.isRunning = false;
        //关闭监控线程
        if(monitorThreads!=null){
            monitorThreads.interrupt();
        }
    }

    @Override
    public void openMonitor(int sleeps, boolean full) {
        this.monitorThreads = new Thread(new Runnable() {

            @Override
            public void run() {
                while(isRunning){
                    try {
                        TimeUnit.SECONDS.sleep(sleeps);
                    } catch (InterruptedException e) {
                        break;
                    }

                    int currSize = BlockThreadPool.this.Queue.size();
                    int max = BlockThreadPool.this.limit;
                    if(full){
                        //如果只有超过90%时记录日志
                        if(currSize >=  (max * 0.9)) {
                            log(currSize,max);
                        }
                    }else {
                        log(currSize,max);
                    }
                }
            }
            private void log(int curr,int max) {
                logger.info(String.format("%s -----Queue:[%d/%d] , Threads:[%d/%d]",BlockThreadPool.this.threadPoolName,curr,max,threadPool.getActiveCount(),threadPool.getMaximumPoolSize()));
            }
        },"【MmonitorThread】");

        this.monitorThreads.start();
    }
}
